home *** CD-ROM | disk | FTP | other *** search
- /* Copyright, 1990, Regents of the University of Colorado */
- /***************************************
- ***************************************
- ** **
- ** IPSC1 Run Time Library for DINO **
- ** REDUCTION function **
- ** **
- ** **
- ***************************************
- ***************************************/
-
- #include "D_lib.h"
- #include "internal.h"
- #include "export.h"
- #include "route.h"
- #include <stdio.h>
- #if D_MACH==D_CUBE
- #include <dos/malloc.h>
- #else
- #include <malloc.h>
- #endif
- #include <ctype.h>
-
-
-
-
- /*****************************
- * *
- * Library variables. *
- * *
- *****************************/
-
- extern int D_ci; /* Channel number. */
-
- D_BOOL NODIAG = FALSE;
-
- static long int loc;
- static int parts,size;
- static D_BOOL contig;
- static long int header[D_RED_HD_SZ];
- static long int header_size = sizeof(header);
-
- /*****************************
- * *
- * Calculate size & *
- * contiquity *
- * *
- *****************************/
-
-
- void D_calc_red_size(P_size,P_contig,P_ddd,P_loc,P_ssd)
- int *P_size;
- long int *P_loc;
- D_BOOL *P_contig;
- D_data_distribution_desc *P_ddd;
- D_storage_space_desc *P_ssd;
- {
- D_BOOL flip;
- int I;
-
- *P_contig = TRUE;
-
- if (P_ddd->needed)
- {
- *P_size = 1;
- flip = FALSE;
-
- /* for (I = 0; I < P_ddd->dims; I++) */
- for (I = P_ddd->dims - 1; I >= 0; I--)
- {
- *P_size *= (P_ddd->range[I].last - P_ddd->range[I].first + 1);
- if (flip)
- {
- if (P_ddd->range[I].last != P_ddd->range[I].first)
- *P_contig = FALSE;
- }
- else
- {
- if (P_ddd->range[I].first != 0 ||
- P_ddd->range[I].last != (P_ddd->range[I].size - 1))
- flip = TRUE;
- }
- }
- if (*P_contig)
- {
- *P_loc = P_ddd->range[0].first;
- for (I = 1; I < P_ddd->dims; I++)
- *P_loc = *P_loc * P_ddd->range[I].size +
- P_ddd->range[I].first;
- }
- }
- else /* (the data distribution descriptor is not needed) */
- /* Calculate size. */
- *P_size = P_ssd->size;
-
- }
- /*****************************
- * *
- * Send Reduction Msg *
- * (all parts if bigger *
- * then max msg size) *
- * *
- *****************************/
-
-
- void D_reduct_send(bufptr,parts,P_first, node, pid, P_type, sub_type,header,
- P_ssd,P_ssd_ind,P_ddd,P_td,P_clist,P_size,P_loc)
- char *bufptr;
- int parts;
- D_BOOL P_first; /* set if this is the first msg of same data
- going to multiple nodes */
- int node,pid,P_type,sub_type,P_size;
- long int P_loc;
- long header[D_RED_HD_SZ];
- D_storage_space_desc *P_ssd, *P_ssd_ind;
- D_data_distribution_desc *P_ddd;
- D_reduct_type_descriptor *P_td;
- D_copy_list *P_clist;
- {
- char *dataptr, *charp, *buf, *indexptr;
- int I,J,K, data_size, index_size,size,type;
- long int offset;
- dataptr = P_ssd->loc + P_loc;
- buf = bufptr;
- offset = 0;
- if (P_first)
- {
-
- /* set up header for sends */
- /* PM */
- header[0] = parts;
- header[1] = (parts > 1)?sub_type:0;
- /* MP */
- header[2] = 1;
- header[3] = node;
- header[4] = pid;
- header[5] = D_ENV_INFO_LEN;
- header[6] = 0;
- /* LM */
- header[8] = 1;
- header[9] = D_ENV_INFO_LEN;
- header[10]=0;
- /* LME */
- header[11] = P_td->D_reduct_type;
- header[12]= 2 * sizeof(long int); /*length of red. header info */
- /* reduction header info */
- header[14]= P_td->D_reduct_data_type;
- header[15]= P_size ; /* size excluding index */
- }
- else
- {
- header[3] = node;
- header[4] = pid;
- }
- if (!contig) ddd_xform(P_ssd,P_ddd,P_clist);
- for (I=1; I<= parts; I++)
- {
- data_size = (parts > I)?
- (int)(D_MAX_MESS - header_size): (int)(P_size - offset);
- /* length of LM *
- header[7] = header_size + data_size - (D_PM_SZ + D_MP_SZ);
- /* length of data , excluding index if applicable */
- header[13] = (long int)data_size;
-
- bufptr = buf;
-
-
- /* copy header to buffer */
- charp = (char *) header;
- for (J=0; J<header_size;J++)
- *(bufptr++) = *(charp++);
-
- /* copy data to buffer */
-
- if (!contig ) copy_data(P_ssd, P_clist,
- (long int) data_size, &bufptr, TRUE);
- else
- for (K = 0; K < data_size; K++)
- *(bufptr++) = *(dataptr++);
- offset += data_size;
-
- if ((P_td->D_reduct_type == D_TYPE_GMINDEX) ||
- (P_td->D_reduct_type == D_TYPE_GMAXDEX))
- {
- indexptr = P_ssd_ind->loc;
- index_size = P_ssd_ind->size;
- for (K=0; K< index_size; K++)
- *(bufptr++) = *(indexptr++);
- }
- else index_size = 0;
- offset += index_size;
-
- size=header_size + data_size + index_size;
- type = ((I==1)?P_type:sub_type);
- /* send out msg using approprate hypercube call */
- #if D_HOST && (D_MACH==D_SIM || D_MACH==D_CUBE)
- sendmsg(D_ci,type,buf,size,node, pid);
- #else
- #if (D_MACH==D_SIM || D_MACH==D_CUBE)
- sendw(D_ci,type,buf,size,node, pid);
- #else
- csend((long)type,buf,(long)size,(long)node, (long)pid);
- #endif
- #endif
- }
-
- }
-
- /*****************************
- * *
- * Recv Reduction Msg *
- * (all parts if bigger *
- * then max msg size) *
- * *
- *****************************/
-
-
- void D_reduct_recv(P_node,P_pid,P_parts,P_ssd,P_ssd_ind,bufptr,P_type,P_td,P_size)
- int P_node,P_pid,P_type;
- int P_parts,P_size;
- D_storage_space_desc *P_ssd,*P_ssd_ind;
- char *bufptr;
- D_reduct_type_descriptor *P_td;
- {
- int I,J;
- int cnt;
- int size, type,node,pid,K;
- long int header[D_RED_HD_SZ],data_size, index_size;
- char *charp,*headptr,*dataptr, *indexptr, *tmpptr;
- int subtype=0;
- dataptr = P_ssd->loc;
- size=D_MAX_MESS;
- for (I=1; I<= P_parts; I++)
- {
- if (I == 1) type=P_type;
- else type=subtype;
-
- #if D_HOST && (D_MACH==D_SIM || D_MACH==D_CUBE)
-
- /* check buffer for P_type */
- /* if not already in buffer, loop */
- /* recvmsg(D_ci, &type, &(D_mess_buf[0]),size, &cnt, &node,&pid);*/
- /* buffer this msg if P_type != type , else break*/
- tmpptr = bufptr;
- D_recvh(D_ci, type, &tmpptr, D_MAX_MESS,&cnt, &node, &pid);
-
-
- #else
- #if (D_MACH==D_SIM || D_MACH==D_CUBE)
- recvw(D_ci, type,&(D_mess_buf[0]),D_MAX_MESS, &cnt, &node, &pid);
- #else
- crecv((long)type,&(D_mess_buf[0]),(long)D_MAX_MESS);
- node=(int)infonode();
- pid=(int)infopid();
- cnt=(int)infocount();
- #endif
- #endif
-
- /* check if correct msg was received */
- if ((node != P_node) || (pid != P_pid))
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog (mypid(),
- "received incorrect msg for this node in reduction call");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;received incorrect msg for this node in reduction call\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
-
- /* copy to header */
-
- charp = bufptr;
- headptr = (char *) header;
-
- for (J=0;J<header_size;J++)
- *(headptr++) = *(charp++);
-
- subtype=(P_parts > 1) ? header[1]:0;
-
- /* check type/size info of msg, if not consistent,
- send msg to syslog & stop computation */
- if(P_size != header[15])
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog (mypid(),
- "received inconsistent data size in reduction call");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;received inconsistent data size in reduction call\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
-
- if (P_td->D_reduct_type != header[11])
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog (mypid(),
- "received wrong red. function msg in reduction call");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;received wrong red. function msg in reduction call\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
-
- if (P_td->D_reduct_data_type != header[14])
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL )
- syslog (mypid(),
- "received inconsistent data element type in reduction call");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;received inconsistent data element type in reduction call\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
-
- /* copy data to data buffer */
- data_size = (int)header[13];
-
- for (K = 0; K < data_size; K++)
- *(dataptr++) = *(charp++);
- if ((P_td->D_reduct_type == D_TYPE_GMINDEX) ||
- (P_td->D_reduct_type == D_TYPE_GMAXDEX))
- {
- indexptr = P_ssd_ind->loc;
- index_size = P_ssd_ind->size;
- for (K=0; K< index_size; K++)
- *(indexptr++) = *(charp++);
- }
- }
- }
-
-
- /*****************************
- * *
- * Free buffers malloced *
- * by library. *
- * *
- *****************************/
-
- /* called by compiler to free buffers.. */
- void D_reduct_free(P_alloc,P_ssd_lib,P_ssd_lhs)
- int P_alloc;
- D_storage_space_desc *P_ssd_lib,*P_ssd_lhs;
- {
- if (P_alloc == 2)
- {
- free((char *)P_ssd_lib->loc);
- free((char *)P_ssd_lhs->loc);
- }
- if (P_alloc == 1) free((char *)P_ssd_lib->loc);
-
- }
-
- /*****************************
- * *
- * reductn function *
- * called by compiler *
- * for all reductions *
- * *
- *****************************/
-
- void D_reductn(P_ssd_lhs,P_ssd_lib,P_ssd_lib_ind,P_ssd_in,P_ssd_in_ind,
- P_ddd_in,P_td,P_es,P_done,P_first,P_alloc,P_step,P_clist)
-
- D_storage_space_desc *P_ssd_lhs,*P_ssd_lib,*P_ssd_lib_ind,*P_ssd_in,
- *P_ssd_in_ind;
- D_data_distribution_desc *P_ddd_in;
- D_reduct_type_descriptor *P_td;
- D_env_set *P_es;
- D_BOOL *P_done,P_first;
- int P_alloc,P_step;
- D_copy_list *P_clist; /* this will change after bob changes the clist
- data structure */
- {
- int node,pid,I,type,e_count;
- envvar *route;
- D_route_type route_type;
- char *tree,*bufptr;
- D_BOOL first;
- if (P_first)
- {
- /* Calculate size and contiguity. */
-
- if (P_td->D_reduct_type != D_TYPE_GMAXDEX &&
- P_td->D_reduct_type != D_TYPE_GMINDEX)
- {
- D_calc_red_size(&size,&contig,P_ddd_in,&loc,P_ssd_in);
- }
- else
- {
- size = P_ssd_in->size;
- contig = TRUE;
- }
-
- /* do necessary mallocs (based on P_alloc) */
-
- /* first check if size is too big to do mallocs on IPSC1 -- */
-
- if (P_alloc < 3 && size > D_MAX_MALLOC_SZ)
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog(mypid(),"Required buffer size too large in reduction call.\n");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;Required buffer size too large in reduction call.\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
-
- if (P_alloc == 2)
- {
- /* malloc lib buffer */
- if ((P_ssd_lib->loc = malloc((unsigned) size)) == NULL)
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog(mypid(), "Error allocating reduction buffer memory.\n");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;Error allocating reduction buffer memory.\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
-
- /* malloc lhs buffer */
- if ((P_ssd_lhs->loc = malloc((unsigned) size)) == NULL)
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog(mypid(), "Error allocating reduction buffer memory.\n");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;Error allocating reduction buffer memory.\n",D_my_env.name,D_my_env.index);
- #endif
- exit(1);
- }
- }
- else
- {
- if (P_alloc == 1)
- /* malloc lib buffer */
- if ((P_ssd_lib->loc = malloc((unsigned) size)) == NULL)
- {
- #if (D_MACH==D_SIM || D_MACH==D_CUBE || D_MACH==D_GRAIL)
- syslog(mypid(), "Error allocating reduction buffer memory.\n");
- #else
- fprintf(stderr,"ENV:%d,INDEX:%d;Error allocating reduction buffer memory.\n",D_my_env.name,D_my_env.index);
- #endif
-
- exit(1);
- }
- }
-
- if (size + header_size > D_MAX_MESS)
- parts = (size + header_size) / D_MAX_MESS + (((size +
- header_size) % D_MAX_MESS)?1:0);
-
- else
- parts=1;
-
- /* modify env. set for routing subroutines */
-
- if (P_es->count > 1)
- {
- e_count = P_es->count;
- for (I=1; I<e_count;I++)
- if (P_es[I].count == 0) P_es->count--;
- }
-
-
-
- /* call D_route_cube_init */
-
- D_route_cube_init(P_es);
-
-
- if (parts > 1)
- D_sub_type = get_type();
-
- } /* end of processing for first red. call */
-
- if (P_step == 1 && (P_td->D_reduct_type != D_TYPE_GMAXDEX &&
- P_td->D_reduct_type != D_TYPE_GMINDEX))
- {
- D_calc_red_size(&size,&contig,P_ddd_in,&loc,P_ssd_in);
- }
-
-
- route = D_route_cube(P_es,P_done,&tree,&route_type,&P_step);
- node = D_env_lookup[route->name][route->index].node;
- pid = D_env_lookup[route->name][route->index].pid;
-
- /* compute msg type for this step */
- type = D_START_RED_MSG_TYPE + P_step;
-
-
- /* route_type == D_route_pair ==> route contains where to
- send & recv from,
- route_type == D_route_rcvsnd ==> send to the nodes in
- the bitmap pointed to by tree(in env. route->name,
- & if tree is null, send to all nodes in route->name.
- recv from the envvar that route points to.
- route_type == D_route_recv ==> recv from the envvar that route
- points to.
- */
-
- bufptr = (char *) &(D_mess_buf[0]);
-
- switch (route_type)
- {
- case D_route_recv:
- D_reduct_recv(node,pid,parts,P_ssd_lib,P_ssd_lib_ind,
- bufptr,type,P_td,size);
- break;
- case D_route_pair:
- D_reduct_send(bufptr,parts,TRUE,node,pid,
- type,D_sub_type,header,P_ssd_in,
- P_ssd_in_ind,P_ddd_in,P_td,P_clist,size,loc);
- D_reduct_recv(node,pid,parts,
- P_ssd_lib,P_ssd_lib_ind,bufptr,type,P_td,size);
- break;
- case D_route_rcvsnd:
- first=TRUE;
- if (tree == NULL)
- {
- /*send to all nodes in envset */
- for (I=0; I< D_env_table[route->name].size; I++)
- {
- D_reduct_send(bufptr,parts,first,
- D_env_lookup[route->name][I].node,
- D_env_lookup[route->name][I].pid,
- type,D_sub_type,header,P_ssd_in,
- P_ssd_in_ind,P_ddd_in,P_td,P_clist,
- size,loc);
- first = FALSE;
- }
- }
- else
- {
- /*send to nodes set in tree */
- for (I=0; I< D_env_table[route->name].size; I++)
- {
- if (tree[I]==1)
- {
- D_reduct_send(bufptr,parts,first,
- D_env_lookup[route->name][I].node,
- D_env_lookup[route->name][I].pid,
- type,D_sub_type,header,P_ssd_in,
- P_ssd_in_ind,P_ddd_in,
- P_td,P_clist,size,loc);
- first = FALSE;
- }
- }
-
- }
- D_reduct_recv(node,pid,parts,
- P_ssd_lib,P_ssd_lib_ind,bufptr,type,P_td,size);
-
- }
- }
-